package com.senthink.gl.business.domain.service;

import com.senthink.gl.business.auth.UpdateUserRequest;
import com.senthink.gl.business.auth.UserDetailRequest;
import com.senthink.gl.business.auth.UserRoleEnum;
import com.senthink.gl.business.common.entity.SearchRequest;
import com.senthink.gl.business.common.exception.DataAccessException;
import com.senthink.gl.business.domain.entity.*;
import com.senthink.gl.business.domain.repository.UserRepository;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

/**
 * @author Ethan
 * @date 2017/11/14
 */
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    /**
     * 用户登录时，根据用户提供的用户标识(账号，邮箱，手机号)来获取用户信息
     *
     * @param username 用户标识(账号，邮箱，手机号)
     * @return Optional
     */
    public Optional<User> loadUser(String username) {

        if (StringUtils.isBlank(username)) {
            return Optional.empty();
        }
        List<User> users;
        try {
            users = userRepository.findByAccountOrMobile(username, username);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
        if (users == null || users.size() == 0) {
            return Optional.empty();
        }
        return Optional.of(users.get(0));
    }



    /**
     * 判断用户是否存在
     *
     * @param account 用户账号
     * @return boolean
     */
    public boolean isUserExistByAccount(String account) {
        long result;

        try {
            result = userRepository.countByAccount(account);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }

        return result > 0;
    }

    /**
     * 判断用户是否存在
     *
     * @param mobile  用户手机号
     * @return boolean
     */
    public boolean isUserExistByMobile(String mobile) {
        long result;

        try {
            result = userRepository.countByMobile(mobile);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }

        return result > 0;
    }




    /**
     * 判断用户是否存在
     *
     * @param account 用户账号
     * @param mobile  用户手机号
     * @return boolean
     */
    public boolean isUserExist(String account, String mobile) {
        long result;

        try {
            result = userRepository.countByAccountOrMobile(account, mobile);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }

        return result > 0;
    }

    /**
     * 保存用户信息
     *
     * @param user 用户
     */
    public User saveUser(User user) {
        try {
            return userRepository.save(user);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
    }

    /**
     * 根据用户账户、邮件、手机获取用户信息
     *
     * @param userDTO
     * @return
     */
    public Optional<User> findByAccountAndEmailAndMobile(UpdateUserRequest userDTO) {
        List<User> users;
        try {
            users = userRepository.findByAccountAndMobile(userDTO.getAccount(), userDTO.getMobile());
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
        if (users == null || users.size() == 0) {
            return Optional.empty();
        }
        return Optional.of(users.get(0));
    }



    /**
     * 根据用户手机获取用户信息
     *
     * @param mobile
     * @return
     */
    public Optional<User> findByMobile(String mobile) {
        List<User> users;
        try {
            users = userRepository.findByMobile(mobile);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
        if (users == null || users.size() == 0) {
            return Optional.empty();
        }
        return Optional.of(users.get(0));
    }

    /**
     * 根据用户账户获取用户信息
     *
     * @param account
     * @return
     */
    public Optional<User> findByAccount(String account) {
        List<User> users;
        try {
            users = userRepository.findByAccount(account);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
        if (users == null || users.size() == 0) {
            return Optional.empty();
        }
        return Optional.of(users.get(0));
    }

    /**
     * 根据用户账户获取用户详情信息
     *
     * @param uid
     * @return
     */
    public Optional<UserDetailRequest> findDetailByUid(String uid) {
        List<UserDetailRequest> users;
        try {
            users = userRepository.findDetailByUid(uid);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
        if (users == null || users.size() == 0) {
            return Optional.empty();
        }
        return Optional.of(users.get(0));
    }

    /**
     * 根据用户账户获取用户信息
     *
     * @param uid
     * @return
     */
    public Optional<User> findByUid(String uid) {
        try {
            return userRepository.findTopByUid(uid);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
    }

    /**
     * 根据用户id删除用户信息
     *
     * @param uid
     */
    public Integer delete(String uid) {
        int n;
        try {
            n = userRepository.deleteByUid(uid);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
        return n;
    }

    /**
     * 根据用户账户、姓名模糊搜索获取用户分页列表
     *
     * @param pageRequest
     * @param searchRequest
     * @return
     */
    public Page<User> findAll(String aid, Boolean enable, String role, PageRequest pageRequest, SearchRequest searchRequest) {
        List<Predicate> predicates = new LinkedList<>();
        Page<User> page = userRepository.findAll((root, query, cb) -> {
            if (StringUtils.isNoneBlank(role)) {
                predicates.add(cb.equal(root.get(User_.role), role));
            }
            if (enable != null) {
                predicates.add(cb.equal(root.get(User_.enable), enable));
            }
            if (StringUtils.isNoneBlank(aid)) {
                Root<UserAreaAuthority> userAreaAuthorityRoot = query.from(UserAreaAuthority.class);
                predicates.add(cb.equal(userAreaAuthorityRoot.get(UserAreaAuthority_.user), root));
                predicates.add(cb.or(cb.equal(userAreaAuthorityRoot.get(UserAreaAuthority_.area).get(Area_.aid), aid),
                        cb.equal(root.get(User_.role), UserRoleEnum.ROLE_ROOT.toString())));
            }
            predicates.add(searchRequest.generatePredicate(root, cb));
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        }, pageRequest);
        return page;
    }

    /**
     * 忘记密码重置密码
     *
     * @param account
     * @param encodePassword
     */
    public void resetPw(String account, String encodePassword) {
        try {
            userRepository.resetPw(account, encodePassword);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
    }


    /**
     * 查询所有管理员用户的手机号码
     *
     * @return
     */
    public List<String> findRootPhones() {
        try {
            return userRepository.findRootPhones(UserRoleEnum.ROLE_ROOT.name(), true);
        } catch (Exception e) {
            throw new DataAccessException(e);
        }
    }
}
